package com.link.base.base.autoconfig.nocode.service;

import com.link.base.base.autoconfig.StringTool;
import com.link.base.base.autoconfig.nocode.model.JavaSourceCodeItem;
import com.link.base.base.autoconfig.nocode.model.LnkInnerCode;
import com.link.base.base.autoconfig.nocode.model.SourceCodeObject;
import com.link.base.base.autoconfig.nocode.model.XmlSourceCodeItem;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.CoreYmlConstants;
import com.link.core.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理类的包名问题
 *
 * @author 何启谦
 * @date 2019/9/28
 */
public class PackageNameProcessor {

    /**
     * 创建SourceCodeObject对象
     */
    public static SourceCodeObject createSourceCodeObject(LnkInnerCode lnkInnerCode) {
        final String packagePrefix = lnkInnerCode.getPackagePrefix();
        if (StringUtils.isNull(packagePrefix)) {
            throw new ServiceException("packagePrefix为空，请检查数据");
        }

        final String entityName = lnkInnerCode.getEntityName();
        if (StringUtils.isNull(entityName)) {
            throw new ServiceException("entityName为空，请检查数据");
        }

        SourceCodeObject sourceCodeObject = new SourceCodeObject();
        sourceCodeObject.setModularUUID(String.valueOf(lnkInnerCode.getHeadId()));
        sourceCodeObject.setModularName(lnkInnerCode.getObjectEntityName());

        sourceCodeObject.setModelJavaCode(new JavaSourceCodeItem(packagePrefix + ".model", entityName, lnkInnerCode.getModelCode()));
        sourceCodeObject.setDaoJavaCode(new JavaSourceCodeItem(
                packagePrefix + ".dao.mybatis.mapper",
                entityName + "Mapper",
                lnkInnerCode.getMapperCode()));
        sourceCodeObject.setServiceJavaCode(new JavaSourceCodeItem(
                packagePrefix + ".service",
                entityName + "Service",
                lnkInnerCode.getServiceCode()));
        sourceCodeObject.setServiceImplJavaCode(new JavaSourceCodeItem(
                packagePrefix + ".service",
                entityName + "ServiceImpl",
                lnkInnerCode.getServiceImpCode()));
        sourceCodeObject.setControllerJavaCode(new JavaSourceCodeItem(
                packagePrefix + ".controller",
                entityName + "Controller",
                lnkInnerCode.getControllerCode()));

        if ("mysql".equals(CoreYmlConstants.getApplicationDatabase())) {
            sourceCodeObject.setDaoXmlCode(new XmlSourceCodeItem(entityName + "MapperMysql", lnkInnerCode.getMysqlXmlCode()));
        } else {
            sourceCodeObject.setDaoXmlCode(new XmlSourceCodeItem(entityName + "Mapper", lnkInnerCode.getOracleXmlCode()));
        }

        transformPackageName(sourceCodeObject, lnkInnerCode);
        return sourceCodeObject;
    }

    private static void transformPackageName(SourceCodeObject sourceCodeObject, LnkInnerCode lnkInnerCode) {
        JavaSourceCodeItem modelJavaCode = sourceCodeObject.getModelJavaCode();
        JavaSourceCodeItem daoJavaCode = sourceCodeObject.getDaoJavaCode();
        JavaSourceCodeItem serviceJavaCode = sourceCodeObject.getServiceJavaCode();
        JavaSourceCodeItem serviceImplJavaCode = sourceCodeObject.getServiceImplJavaCode();
        JavaSourceCodeItem controllerJavaCode = sourceCodeObject.getControllerJavaCode();
        XmlSourceCodeItem daoXmlCode = sourceCodeObject.getDaoXmlCode();
        List<JavaSourceCodeItem> otherJavaCodes = sourceCodeObject.getOtherJavaCodes();
        if (otherJavaCodes == null) {
            otherJavaCodes = new ArrayList<>();
        }

        String modelPackageName = modelJavaCode.getPackageName();
        if (!modelPackageName.endsWith(".model")) {
            throw new RuntimeException("model包名称不符合规范");
        }
        String modularPackageName = modelPackageName.replace(".model", "");
//        String newModularPackageName = modularPackageName + "." + entityName.toLowerCase() + "." + codeVersion;
        String entityName = lnkInnerCode.getEntityName();
        String packageVersion = "v" + lnkInnerCode.getCodeVersion();
        String newModularPackageName = "com.link.nocode.base.dynamic." + entityName.toLowerCase() + "." + packageVersion;

        List<String> sourcePackageNames = new ArrayList<>();
        sourcePackageNames.add(modelJavaCode.getPackageName());
        sourcePackageNames.add(daoJavaCode.getPackageName());
        sourcePackageNames.add(serviceJavaCode.getPackageName());
        sourcePackageNames.add(serviceImplJavaCode.getPackageName());
        sourcePackageNames.add(controllerJavaCode.getPackageName());
        for (JavaSourceCodeItem item : otherJavaCodes) {
            sourcePackageNames.add(item.getPackageName());
        }

        Map<String, String> regexMap = new HashMap<>();
        for (String item : sourcePackageNames) {
            String targetPackageName = StringTool.replaceAll(item, modularPackageName, newModularPackageName);
            regexMap.put(item, targetPackageName);
        }
        transformPackageName(modelJavaCode, regexMap);
        transformPackageName(daoJavaCode, regexMap);
        transformPackageName(serviceJavaCode, regexMap);
        transformPackageName(serviceImplJavaCode, regexMap);
        transformPackageName(controllerJavaCode, regexMap);
        for (JavaSourceCodeItem item : otherJavaCodes) {
            transformPackageName(item, regexMap);
        }
        transformXml(daoXmlCode, regexMap);
    }

    private static void transformPackageName(JavaSourceCodeItem codeObject, Map<String, String> regexMap) {
        String newPackageName = StringTool.replaceAll(codeObject.getPackageName(), regexMap);
        codeObject.setPackageName(newPackageName);

        String newCodeContent = StringTool.replaceAll(codeObject.getCodeContent(), regexMap);

        // ------
        // 临时做法，新版的自动配置的"com.hand" 包已改成 "com.link"; by 2019-09-29 heqiqian
        newCodeContent = StringTool.replaceAll(newCodeContent, "com.hand.", "com.link.");
        // ------

        codeObject.setCodeContent(newCodeContent);
    }

    private static void transformXml(XmlSourceCodeItem codeObject, Map<String, String> regexMap) {
        String newCodeContent = StringTool.replaceAll(codeObject.getCodeContent(), regexMap);

        // ------
        // 临时做法，新版的自动配置的"com.hand" 包已改成 "com.link"; by 2019-09-29 heqiqian
        newCodeContent = StringTool.replaceAll(newCodeContent, "com.hand.", "com.link.");
        // ------

        codeObject.setCodeContent(newCodeContent);
    }

}
